﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;

namespace FierceWar
{
	public class MenuEntry
	{
		public enum MenuEntryState
		{
			None,
			Hover,
			Pressed,
			Released,
		}

		private GameResources _resources;

		// Font.
		private SpriteFont _font;
		public SpriteFont Font
		{
			get
			{
				return _font;
			}
			set
			{
				_font = value;
				FontText = _font.MeasureString(_text);
			}
		}

		// Color of the text.
		private Color _color;

		public Color NormalColor;
		public Color HoverColor;
		public Color BlinkColor;

		// Text is here.
		private string _text;
		
		// Measure of the text.
		public Vector2 FontText;
		
		// Blink ?
		private bool _isBlink;
		public bool IsBlink
		{
			get
			{
				return _isBlink;
			}
		}
		
		// Visible ?
		private bool _isVisible;
		
		// Duration of the blink.
		private float _blinkDuration;

		// Time slice to switch between visible and invisible.
		private float _blinkTimeSlice;

		// Yeah, it's just stopwatch.
		private float _stopwatch;

		// Rectangle around the text.
		private Rectangle _rectangle;

		// Position of the text.
		private Vector2 _position;
		public Vector2 Position
		{
			get
			{
				return _position;
			}
			set
			{
				_position = value;
				_rectangle = new Rectangle((int)_position.X, (int)_position.Y,
					(int)FontText.X, (int)FontText.Y);
			}
		}

		// State of the menu entry.
		public MenuEntryState State;

		public bool FunctionEnable = true;

		public Vector2 ShadowOffset = new Vector2(2.0f);

		private bool _soundHoverEnable = true;
		public SoundEffectInstance MenuClick;

		public MenuEntry(GameResources resources, string text,
			float blinkDuration, float blinkTimeSlice)
		{
			_resources = resources;
			_text = text;
			_blinkDuration = blinkDuration;
			_blinkTimeSlice = blinkTimeSlice;

			Font = resources.MenuFont;

			State = MenuEntryState.None;

			NormalColor = Color.White * 0.7f;
			HoverColor = Color.LightCoral;
			BlinkColor = Color.Goldenrod;
			_color = NormalColor;

			_isBlink = false;
			_isVisible = true;
			_stopwatch = _blinkDuration;

			MenuClick = resources.MenuClick.CreateInstance();
		}

		/// <summary>
		/// Determines whether the mouse is hover on the text.
		/// </summary>
		/// <returns>
		///   <c>true</c> if this instance is hover; otherwise, <c>false</c>.
		/// </returns>
		private bool isHover()
		{
			int mouseX = (int)MouseInput.Position.X;
			int mouseY = (int)MouseInput.Position.Y;
			if ((mouseX < _rectangle.Left) ||
				(mouseX > _rectangle.Right) ||
				(mouseY < _rectangle.Top) ||
				(mouseY > _rectangle.Bottom))
			{
				return false;
			}

			return true;
		}

		public void Update(GameTime gameTime)
		{
			if (isHover())
			{
				if (MouseInput.IsLeftPress)
				{
					// Pressed.
					State = MenuEntryState.Pressed;
					_color = BlinkColor;
					if (MenuClick.State == SoundState.Stopped)
					{
						MenuClick.Play();
					}
				}
				else if (MouseInput.IsLeftButtonReleased)
				{
					// Released.
					_color = NormalColor;
					if (FunctionEnable)
					{
						_isBlink = true;
					}
				}
				else
				{
					// Just hover and do nothing.
					State = MenuEntryState.Hover;
					_color = HoverColor;
					if (_soundHoverEnable)
					{
						_resources.MenuHover.Play();
						_soundHoverEnable = false;
					}
				}
			}
			else
			{
				// Outside the text.
				State = MenuEntryState.None;
				_color = NormalColor;
				_soundHoverEnable = true;
			}

			// Handle blink.
			if (_isBlink)
			{
				_color = BlinkColor;
				_stopwatch -= (float)gameTime.ElapsedGameTime.TotalMilliseconds;
				_blinkTimeSlice -= (float)gameTime.ElapsedGameTime.TotalMilliseconds;
				if (_blinkTimeSlice < 0.0f)
				{	
					// Reset time-slice.
					_blinkTimeSlice = 100.0f;
					_isVisible = !_isVisible;
				}

				if (_stopwatch < 0.0f)
				{	
					// Reset stopwatch.
					_stopwatch = _blinkDuration;
					_isBlink = false;
					_isVisible = true;

					// Event invoke now!
					State = MenuEntryState.Released;
				}
			}
		}

		public void Draw()
		{
			if (_isVisible)
			{
				// Draw shadow of text.
				_resources.SpriteBatch.DrawString(
						Font, _text,
						_position + ShadowOffset, Color.Black);
				// Draw text.
				_resources.SpriteBatch.DrawString(
						Font, _text, _position, _color);
			}
		}
	}
}
